package gdut.imis.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import gdut.imis.Utils.Constants;
import gdut.imis.Utils.RedisCache;
import gdut.imis.Utils.Result;
import gdut.imis.Utils.WebUtils;
import gdut.imis.domain.Manager;
import gdut.imis.domain.University;
import gdut.imis.domain.User;
import gdut.imis.enums.Status;
import gdut.imis.mapper.ManagerMapper;
import gdut.imis.service.ManagerService;
import gdut.imis.service.UniversityService;
import gdut.imis.service.UserService;
import gdut.imis.vo.ManagerVo;
import gdut.imis.vo.UserLoginVo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Objects;
import java.util.UUID;

/**
 * @Description
 * @Author JiaFu
 * @Date 2023/4/8 18:26
 */
@Service
@RequiredArgsConstructor
public class ManagerServiceImpl extends ServiceImpl<ManagerMapper, Manager> implements ManagerService {
    private final RedisCache redisCache;
    private final UserService userService;
    private final UniversityService universityService;
    private final ManagerMapper managerMapper;
    private final PasswordEncoder passwordEncoder;
    @Value("${env-file-path.base-path}")
    private String basePath;

    @Override
    public Result uploadAvatar(MultipartFile file) throws IOException {
        if (Objects.isNull(file)) {
            return Result.errorWithArgs(Status.REQUEST_PARAMS_NOT_VALID_ERROR, "file");
        }
        //构建文件存储路径
        String path = basePath + Constants.IMAGES;
        File dirFile = new File(path);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        String fileName = file.getOriginalFilename();
        int index = fileName.lastIndexOf(".");
        String suffix = fileName.substring(index);
        fileName = UUID.randomUUID().toString().replaceAll("-", "").concat(suffix);
        path = path + Constants.SEPARATOR + fileName;
        file.transferTo(new File(path));
        //获取当前操作的管理员信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserLoginVo userLoginVo = (UserLoginVo) authentication.getPrincipal();
        //是管理员
        if (userLoginVo.getIsManager()) {
            //更新数据库里管理员信息
            Manager manager = userLoginVo.getManager();
            manager.setAvatarUrl(path);
            boolean flag = this.updateById(manager);
            if (flag) {//redis端管理员的信息也要更新
                userLoginVo.setManager(manager);
                redisCache.setCacheObject("login:" + manager.getPhone(), userLoginVo);
                return Result.success();
            }
        } else {
            //是普通用户
            User user = userLoginVo.getUser();
            user.setAvatarUrl(path);
            boolean flag = userService.updateById(user);
            if (flag) {//redis端用户信息也需要更新
                userLoginVo.setUser(user);
                redisCache.setCacheObject("login:" + user.getIdCard(), userLoginVo);
                return Result.success();
            }
        }
        return Result.errorWithArgs(Status.FAILED, "更新用户头像信息失败");
    }

    @Override
    public void downloadAvatar(String avatarUrl, HttpServletResponse response) throws FileNotFoundException {
        File file = new File(avatarUrl);
        if (!file.exists()) {
            WebUtils.renderString(response, avatarUrl + "文件不存在");
            return;
        }
        FileInputStream inputStream = null;
        ServletOutputStream outputStream = null;
        try {
            //输入流，读取文件内容
            inputStream = new FileInputStream(file);
            //输出流，通过流将文件写回浏览器
            outputStream = response.getOutputStream();
            response.setContentType("image/jpeg");
            int len = 0;
            byte[] bytes = new byte[1024];
            while ((len = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
                outputStream.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            try {
                inputStream.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public Result getManagerInfo() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserLoginVo userLoginVo = (UserLoginVo) authentication.getPrincipal();
        if (userLoginVo != null) {
            if (userLoginVo.getIsManager()) {
                Manager manager = userLoginVo.getManager();
                if (Objects.isNull(manager)) {
                    return Result.errorWithArgs(Status.FAILED, "获取管理员信息失败");
                }
                ManagerVo managerVo = new ManagerVo();
                University university = universityService.getById(manager.getUniversityId());
                BeanUtils.copyProperties(manager, managerVo);
                managerVo.setUniversity(university.getSchoolName());
                managerVo.setUniversityLogoUrl(university.getSchoolLogo());
                return Result.success(managerVo);
            }
            return Result.errorWithArgs(Status.FAILED, "不是管理员账户");
        }
        return Result.errorWithArgs(Status.FAILED, "用户未登录");
    }

    /***
     * @param 更新管理员基本信息
     * @param: manager
     * @return Result
     */
    @Override
    public Result updateManagerInfo(Manager manager) {
        if (Objects.isNull(manager)) {
            return Result.errorWithArgs(Status.REQUEST_PARAMS_NOT_VALID_ERROR, "manager");
        }
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserLoginVo userLoginVo = (UserLoginVo) authentication.getPrincipal();
        if (userLoginVo.getIsManager()) {
            boolean flag = this.updateById(manager);
            if (flag) {
                //数据库信息更新成功后，redis也要更新
                userLoginVo.setManager(manager);
                redisCache.setCacheObject("login:" + manager.getPhone(), userLoginVo);
                return Result.success();
            }
            return Result.errorWithArgs(Status.FAILED, "更新管理员信息失败");
        }
        return Result.errorWithArgs(Status.FAILED, "非管理员用户");
    }

    /***
     * 根据管理员的类型查询管理员列表（分页查询）
     * @param: type
     * @param: pageNo
     * @param: pageSize
     * @return Result
     */
    @Override
    public Result getPageManagerListByType(Integer type, Integer pageNo, Integer pageSize, Long universityId) {
        if (Objects.isNull(type)) {
            return Result.errorWithArgs(Status.REQUEST_PARAMS_NOT_VALID_ERROR, "type");
        }
        Page<ManagerVo> page = new Page<>();
        page.setCurrent(pageNo);
        page.setSize(pageSize);
        Page<ManagerVo> resPage = managerMapper.getPageManagerListByType(type, page, universityId);
        if (resPage != null && resPage.getTotal() > 0) {
            return Result.success(resPage);
        }
        return Result.errorWithArgs(Status.FAILED, "没有任何管理员信息");
    }

    /***
     * 根据id删除管理员
     * @param: id
     * @return Result
     */
    @Override
    public Result deleteManagerById(Integer id) {
        if (id != null) {
            boolean flag = this.removeById(id);
            if (flag) {
                return Result.success();
            }
            return Result.errorWithArgs(Status.FAILED, "删除管理员失败");
        }
        return Result.errorWithArgs(Status.REQUEST_PARAMS_NOT_VALID_ERROR, "id");
    }

    /***
     * 新增管理员
     * @param: manager
     * @return Result
     */
    @Override
    public Result addManager(Manager manager) {
        if (Objects.isNull(manager)) {
            return Result.errorWithArgs(Status.REQUEST_PARAMS_NOT_VALID_ERROR, "manager");
        }
        //判断该手机号是否已被使用
        Manager one = this.getOne(new LambdaQueryWrapper<Manager>().eq(Manager::getPhone, manager.getPhone()));
        if (one != null) {
            return Result.errorWithArgs(Status.FAILED, "该手机号已被使用,请更换其他手机号");
        }
        String avatarUrl = basePath + Constants.IMAGES + Constants.SEPARATOR + Constants.DEFAULT_PNG;
        //默认密码为手机号
        String password = passwordEncoder.encode(manager.getPhone());
        manager.setAvatarUrl(avatarUrl);
        manager.setPassword(password);
        boolean flag = this.save(manager);
        if (flag) {
            return Result.success();
        }
        return Result.errorWithArgs(Status.FAILED, "新增管理员失败");
    }


    /***
     * 根据学校id分页查询该校教师信息（三级管理员次才有的权限）
     * @param: id
     * @param: pageNo
     * @param: pageSize
     * @return void
     */
    @Override
    public Result getPageTeachersByUniversityId(Long id, Integer pageNo, Integer pageSize) {
        Page<User> page = new Page<>();
        page.setCurrent(pageNo);
        page.setSize(pageSize);
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUniversityId, id);
        queryWrapper.eq(User::getType, 1);
        Page<User> resPage = userService.page(page, queryWrapper);
        if (resPage != null && resPage.getTotal() > 0) {
            return Result.success(resPage);
        }
        return Result.errorWithArgs(Status.FAILED, "没有查询到任何教师信息");
    }

    /***
     * 新增教师类型的用户（三级管理员拥有的权限）
     * @param: user
     * @return Result
     */
    @Override
    public Result addTeacherUser(User user) {
        if (Objects.isNull(user)) {
            return Result.errorWithArgs(Status.REQUEST_PARAMS_NOT_VALID_ERROR, "user");
        }
        //判断该身份证号是否已被使用
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getIdCard, user.getIdCard());
        User one = userService.getOne(queryWrapper);
        if (one != null) {
            return Result.errorWithArgs(Status.FAILED, "该身份证号已被使用");
        }
        //默认头像url
        String avatarUrl = basePath + Constants.IMAGES + Constants.SEPARATOR + Constants.DEFAULT_PNG;
        //用户默认密码为身份证后六位
        String idCard = user.getIdCard();
        String password = idCard.substring(idCard.length() - 6);
        password = passwordEncoder.encode(password);
        user.setAvatarUrl(avatarUrl);
        user.setPassword(password);
        boolean flag = userService.save(user);
        if (flag) {
            return Result.success();
        }
        return Result.errorWithArgs(Status.FAILED, "新增教师失败");
    }

    /***
     * 根据用户id删除对应的老师（三级管理员才有的权限）
     * @param: userId
     * @return Result
     */
    @Override
    public Result deleteTeacherUserById(Long userId) {
        boolean flag = userService.removeById(userId);
        if (flag) {
            return Result.success();
        }
        return Result.errorWithArgs(Status.FAILED, "删除教师失败");
    }

    /***
     * 下载档案录入权限申请的证明材料文件（三级管理员才有的权限）
     * @param: url
     * @param: response
     * @return void
     */
    @Override
    public void downloadProveFile(String url, HttpServletResponse response) throws FileNotFoundException {
        //查看文件是否存在
        File file = new File(url);
        if (!file.exists()) {
            Result<Object> res = Result.errorWithArgs(Status.FAILED, "文件不存在");
            WebUtils.renderString(response, res.toString());
            return;
        }
        FileInputStream inputStream = null;
        ServletOutputStream outputStream = null;
        try {
            //获取文件名
            String fileName = file.getName();
            //获取输入流
            inputStream = new FileInputStream(file);
            //获取输出流
            outputStream = response.getOutputStream();
            //设置response响应属性
//            response.reset();//清空response
            response.setContentType("application/octet-stream");
            response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            byte[] bytes = new byte[1024];
            int len;
            while ((len = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
                outputStream.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}
